package com.lujieni.moon.filter;

import com.alibaba.fastjson.JSON;
import com.lujieni.moon.dto.ResponseDto;
import com.lujieni.moon.utils.JWTUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseCookie;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

/**
 * @author
 * @Title: JWTVerifyGlobalFilter
 * @Description:
 * @date 2022/10/18 2:12 下午
 */
public class JWTVerifyGlobalFilter implements GlobalFilter, Ordered {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    private static final AntPathMatcher antPathMatcher = new AntPathMatcher();


    @Value("${noNeedCheckUri:''}")
    private List<String> noNeedCheckUri;

    private JWTUtils jwtUtils;

    public JWTUtils getJwtUtils() {
        return jwtUtils;
    }

    public void setJwtUtils(JWTUtils jwtUtils) {
        this.jwtUtils = jwtUtils;
    }

    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();


        /**
         * 哪些uri不需要校验
         */
        String path = exchange.getRequest().getPath().toString();
        if(!CollectionUtils.isEmpty(noNeedCheckUri)){
            for (String pattern : noNeedCheckUri) {
                if(antPathMatcher.match(pattern, path)){
                    return chain.filter(exchange);
                }
            }
        }

        Map<String, String> headers = request.getHeaders().toSingleValueMap();
        String token = headers.get("token");
        if(StringUtils.isEmpty(token)){
            HttpCookie name  = request.getCookies().getFirst("token"); //从cookie中获取
            if(name != null){
                token = name.getValue();
            }
        }
        if(StringUtils.isEmpty(token)){
            token = request.getQueryParams().getFirst("token"); //从requestParam里取
        }

        if(StringUtils.isEmpty(token)){
            token = jwtUtils.generateRenewToken("181268");
            ResponseDto responseDto = ResponseDto.builder().errorCode("401").success(false).build();
            DataBuffer buffer = response.bufferFactory().wrap(JSON.toJSONString(responseDto).getBytes(StandardCharsets.UTF_8));
            response.setStatusCode(HttpStatus.OK);
            response.getHeaders().add(HttpHeaders.CONTENT_TYPE, "application/json;charset=UTF-8");
            response.getHeaders().add("token", token);
            return response.writeWith(Mono.just(buffer));
        }else{

            /**
             * 1. 校验token的有效性
             * 2. 如果是ok的就续期
             * 3. 将成功续期的token返回给前端 将从token中获取的userCode传递给目标服务的头
             */
            String userCode = jwtUtils.getClaimFromToken(token);
            if(StringUtils.isEmpty(userCode)){
                token = jwtUtils.generateRenewToken("181268");
                ResponseDto responseDto = ResponseDto.builder().errorCode("401").success(false).build();
                DataBuffer buffer = response.bufferFactory().wrap(JSON.toJSONString(responseDto).getBytes(StandardCharsets.UTF_8));
                response.setStatusCode(HttpStatus.OK);
                response.getHeaders().add(HttpHeaders.CONTENT_TYPE, "application/json;charset=UTF-8");
                response.getHeaders().add("token", token);
                return response.writeWith(Mono.just(buffer));
            }

            String generateRenewToken = jwtUtils.generateRenewToken(userCode);

            ResponseCookie responseCookie =
                    ResponseCookie.from("token", generateRenewToken)
                            .maxAge(3600)
                            .domain("localhost")
                            .path("/").httpOnly(true)
                            .build();
            request = exchange.getRequest().mutate()
                    .header("userCode", userCode) // 可以连续添加多个header到后端服务不会影响原本请求的header
                    .header("haha", "haha")
                    .build();
            response.addCookie(responseCookie); //gateway中可以设置返回给前端的cookie



            return chain.filter(exchange.mutate().request(request).response(response).build());
        }
    }

    public int getOrder() {
        return 0;
    }
}
